﻿package datapool.resource
{
	import flash.net.URLRequest;
	import flash.events.IOErrorEvent;
	import flash.events.Event;
	import flash.net.URLLoader;
	import flash.display.Loader;
	import flash.utils.Dictionary;
	public class RemoteResource
	{
		static private var _rs:RemoteResource;
		static public var PRIORITY_LOW:int    = 2;
		static public var PRIORITY_NORMAL:int = 1;
		static public var PRIORITY_HIGH:int   = 0;
		
		private var _loader:Loader;
		
		private const STAT_FREE:int = 0;
		private const STAT_BUSY:int = 1;
		private var _status:int;
		
		private var _curRS:RSCallbackFunctionObj;
		private var _normalReqRS:Array;      //普通优先级URL请求
		private var _lowReqRs:Array;   //低优先级URL请求
		private var _highReqRs:Array;  //高优先级URL请求
		private var _reqRSs:Array;     //请求队列-包含前面三个优先级
		private var _resources:Dictionary;
		
		public function RemoteResource():void
		{
			_normalReqRS = new Array();
			_lowReqRs    = new Array();
			_highReqRs   = new Array();
			_reqRSs      = new Array();
			_reqRSs.push(_highReqRs);
			_reqRSs.push(_normalReqRS);
			_reqRSs.push(_lowReqRs);
			_resources = new Dictionary();
			
			_loader = new Loader();
			_loader.contentLoaderInfo.addEventListener(Event.OPEN, onOpen);
			_loader.contentLoaderInfo.addEventListener(Event.COMPLETE, onComplete);
			_loader.contentLoaderInfo.addEventListener(IOErrorEvent.IO_ERROR, onError);
			_status = STAT_FREE;
		}
		
		static public function getInstance():RemoteResource
		{
			if(!_rs)
			{
				_rs = new RemoteResource();
			}
			return _rs;
		}
		
		public function requestRs(url:String, oncomplete:Function, onProgress:Function=null, onOpen:Function=null, priority:int=1):void
		{
			if(_resources[url] && oncomplete!=null)
			{
				oncomplete(_resources[_curRS.url]);
				return;
			}
			
			var rsCallbackFunctionObj:RSCallbackFunctionObj = new RSCallbackFunctionObj();
			rsCallbackFunctionObj.url        = url;
			rsCallbackFunctionObj.onOpen     = onOpen;
			rsCallbackFunctionObj.onComplete = oncomplete;
			rsCallbackFunctionObj.onProgress = onProgress;
			_reqRSs[priority].push(rsCallbackFunctionObj);
			//_reqRS.push(rsCallbackFunctionObj);
						
			loadRs();
		}
		
		private function getNextReqObj():RSCallbackFunctionObj
		{
			var reqObj:RSCallbackFunctionObj;
			var arrTmp:Array;
			var i:int;
			for(i=0; i<_reqRSs.length; i++)
			{
				arrTmp = _reqRSs[i] as Array;
				reqObj = arrTmp.shift();
				if(reqObj)
				{
					return reqObj;
				}
			}
			
			return null;
		}
		
		private function loadRs():void
		{
			if(_status == STAT_FREE)
			{
				_curRS = getNextReqObj();
				if (_curRS)
				{
					trace(this, _curRS.url);
					
					if(_resources[_curRS.url])
					{
						trace(this, "try to load a loaded RS");
						_curRS.onComplete(_resources[_curRS.url]);
						_status = STAT_FREE;
						loadRs();
						return;
					}
					_status = STAT_BUSY;
					_loader.load(new URLRequest(_curRS.url));
					return;
				}
				else
				{
					_status = STAT_FREE;
				}
			}
		}
		
		private function onOpen(e:Event):void
		{
			if (_curRS && _curRS.onOpen!=null)
			{
				_curRS.onOpen();
			}
		}
		
		private function onComplete(e:Event):void
		{
			_resources[_curRS.url] = _loader.content;
			_curRS.onComplete(_resources[_curRS.url]);
			_status = STAT_FREE;
			loadRs();
		}
		
		private function onError(e:IOErrorEvent):void
		{
//			_urlLoader.removeEventListener(Event.OPEN, onOpen);
//			_urlLoader.removeEventListener(Event.COMPLETE, onComplete);
//			_urlLoader.removeEventListener(IOErrorEvent.IO_ERROR, onError);
			loadRs();
			trace(this, "loadFailed", _curRS.url);
			trace(this, e.text);
		}
	}
}
